package com.atguigu.gulimall.seckill;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;


/**
 * 秒杀系统
 * 1、服务单一部署，自己挂掉，也不会影响别的服务
 * 2、秒杀链接加密，防止恶意攻击，防止链接暴露，自己工作人员，提前秒杀商品
 * 3、库存预热，秒杀读多写少，虚无每次，使用库存预热，放到redis里，使用信号量控制进来的秒杀的请求
 * 3.5、redis集群，分片高可用的集群
 * 4、nginx做好动静分离，动态请求才发给网关，静态请求全部交给nginx处理，使用CDN网络，分担网络压力
 * 5、恶意请求拦截，识别恶意请求并拦截，网关层拦截
 * 6、流量错峰，将瞬时流量分散到不通的时间点，如输入验证码，加入购物车等等
 * 7、限流、熔断、降级 限制次数、限制总量，可以前端限流或后端限流，快速失败降级允许，熔断隔离防止雪崩
 *  1、限流 sentinel+sentinel dashboard，在dashboard配置微服务层controller接口层的拦截
 *  2、熔断 feign+sentinel 配置 feign.sentinel.enabled=true，
 *        1) 远程服务调用方配置feign.sentinel.enabled=true，
 *        2)  调用方feign接口中 配置 fallback = SeckillFeignServiceFallBack.class
 *            失败后要调用的本地方法，实现这个接口，重写熔断后的实现,熔断是针对远程服务挂掉熔断的情况
 *
 *        服务提供方指定降级策略，
 *        这种一般是在运行的时候，某个服务的方法顶部压力而自己熔断，超大浏览的时候，必须牺牲一些远程服务，提供方是在允许，但是不运行自己的业务逻辑，是默认的熔断数据
 *  3、降级 在sentinel dashboard 调用方手动指定远程服务的降级策略，远程服务被降级处理
 *  4、自定义受保护资源
 *     1）try(){}catch{Entry entry = SphU.entry("seckillSkus//资源名"){//这里是受保护的资源}}
 *     2）基于注解 @SentinelResource(blockHandler = "seckillSkus//资源名"，blockHandler="seckillSkus//降级的备用资源名，方法名和返回值要一摸一样") + 自定义流控方法
 *     降级是针对某个服务太慢而手动熔断的方法，等不及调用了，按照响应时间设置
 *
 *  5、网关层控流，直接不访问controller微服务了，在网关层就拦截了
 *     网关导入spring-cloud-alibaba
 *
 * 8、队列削峰，每1000秒杀商品，所有秒杀成功的请求，放到队列里面，慢慢创建订单，扣件库存即可
 *
 */


//@EnableRabbit，只有要监听消息的时候才加，发消息的时候不加
@EnableFeignClients
@EnableScheduling
@EnableDiscoveryClient
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})  //排除掉mybatis
public class GulimallSeckillApplication {

	public static void main(String[] args) {
		SpringApplication.run(GulimallSeckillApplication.class, args);
	}

}
